package com.chengqs.dfs.datanode.server;

import com.chengqs.dfs.namenode.rpc.model.HeartbeatRequest;
import com.chengqs.dfs.namenode.rpc.model.HeartbeatResponse;
import com.chengqs.dfs.namenode.rpc.model.RegisterRequest;
import com.chengqs.dfs.namenode.rpc.model.RegisterResponse;
import com.chengqs.dfs.namenode.rpc.service.NameNodeServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.netty.NegotiationType;
import io.grpc.netty.NettyChannelBuilder;
import lombok.extern.slf4j.Slf4j;

/**
 * <B>主类名称：</B>NameNodeServiceActor<BR>
 * <B>概要说明：</B>负责跟一组NameNode中的某一个进行通信的线程组件<BR>
 *
 * @author: chengqs
 * @create: 2025-03-30 03:46:28
 **/
@Slf4j
public class NameNodeServiceActor {
    private static final String NAME_NODE_HOSTNAME = "localhost";
    private static final int NAME_NODE_PORT = 50070;

    private final NameNodeServiceGrpc.NameNodeServiceBlockingStub nameNode;

    public NameNodeServiceActor() {
        ManagedChannel channel = NettyChannelBuilder
                .forAddress(NAME_NODE_HOSTNAME, NAME_NODE_PORT)
                .negotiationType(NegotiationType.PLAINTEXT)
                .build();
        this.nameNode = NameNodeServiceGrpc.newBlockingStub(channel);
    }

    /**
     * 向自己负责通信的那个NameNode进行注册
     */
    public void register() throws Exception {
        Thread registerThread = new RegisterThread();
        registerThread.start();
        registerThread.join();
    }

    /**
     * 开启发送心跳的线程
     */
    public void startHeartbeat() {
        new HeartbeatThread().start();
    }

    /**
     * 负责注册的线程
     *
     * @author zhonghuashishan
     */
    class RegisterThread extends Thread {

        @Override
        public void run() {
            try {
                // 发送rpc接口调用请求到NameNode去进行注册
                log.info("发送RPC请求到NameNode进行注册.......");

                // 在这里进行注册的时候会提供哪些信息过去呢？
                // 比如说当前这台机器的ip地址、hostname，这两个东西假设是写在配置文件里的
                // 我们写代码的时候，主要是在本地来运行和测试，有一些ip和hostname，就直接在代码里写死了
                // 大家后面自己可以留空做一些完善，你可以加一些配置文件读取的代码
                String ip = "127.0.0.1";
                String hostname = "dfs-data-01";
                // 通过RPC接口发送到NameNode他的注册接口上去
                RegisterRequest request = RegisterRequest
                        .newBuilder()
                        .setIp(ip)
                        .setHostname(hostname)
                        .build();

                RegisterResponse response = nameNode.register(request);
                log.info("接收到NameNode返回的注册响应：{}", response.getStatus());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    class HeartbeatThread extends Thread {

        @Override
        public void run() {
            try {
                while (true) {
                    log.info("发送RPC请求到NameNode进行心跳......");

                    String ip = "127.0.0.1";
                    String hostname = "dfs-data-01";

                    HeartbeatRequest request = HeartbeatRequest
                            .newBuilder()
                            .setIp(ip)
                            .setHostname(hostname)
                            .build();

                    HeartbeatResponse response = nameNode.heartbeat(request);
                    log.info("接收到NameNode返回的心跳响应：{}", response.getStatus());

                    Thread.sleep(30 * 1000);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
